package org.java.gateway.config;

import org.java.gateway.Api.OAuthLogout;
import org.java.gateway.handle.OAuth2LogoutHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.logout.DelegatingServerLogoutHandler;
import org.springframework.security.web.server.authentication.logout.HttpStatusReturningServerLogoutSuccessHandler;
import org.springframework.security.web.server.authentication.logout.SecurityContextServerLogoutHandler;
import org.springframework.security.web.server.authentication.logout.ServerLogoutHandler;

@Configuration
@EnableWebFluxSecurity//相当于servlet;
//激活远程Feign功能
@EnableFeignClients(clients = OAuthLogout.class)
public class OAuthClientConfig {
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http){
        // 排除不需要权限的路径，主要是登录地址、验证码等
        http.authorizeExchange()
                .pathMatchers(
                        "/favicon.ico",
                        "/*/actuator/**",
                        "/actuator/**",
                        "/oauth/login/code/*"
                )
                .permitAll();
        // 其他路径都需要授权
        // 一次请求、就会包含一个响应，请求和响应加在一起就是一个Exchange。
        http.authorizeExchange().anyExchange().authenticated();

        // 激活OAuth 2.0的登录
        http.oauth2Login();
        // 退出登录
        http.logout()
                // 退出登录的地址，需要加上/api
                .logoutUrl("/logout")
                //处理退出登录的操作
                .logoutHandler(logoutHandler())
                //退出登录之后，如何返回结果，默认是重定向
                //HttpStatusReturningServerLogoutSuccessHandler
                .logoutSuccessHandler(new HttpStatusReturningServerLogoutSuccessHandler());

        // 禁用CSRF（防止跨站攻击），目的是为了给前端使用的时候能够跨站访问，不需要验证CSRF的令牌。
        http.csrf().disable();
        return http.build();
    }

    @Autowired
    private OAuth2LogoutHandler oAuth2LogoutHandler;

    private ServerLogoutHandler logoutHandler() {
        //默认退出登录，把Session里面的用户信息删除
        SecurityContextServerLogoutHandler localLogout = new SecurityContextServerLogoutHandler();
        //把多个退出登录处理程序包装成一个退出登录处理程序
        //这里使用了【组合设计模式】，此模式就是把多个不同的组件，组合在一起
        DelegatingServerLogoutHandler logoutHandler = new DelegatingServerLogoutHandler(localLogout,oAuth2LogoutHandler);
        return logoutHandler;
    }
}
